﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Interfaces;

namespace Model
{
    public class Årsregnskab : IÅrsregnskabsdata
    {
        // attributter
        private int årstal;
        private double immaterielle;
        private double materielle;
        private double finansielle;
        private double varebeholdninger;
        private double tilgodehavender;
        private double værdipapirer;
        private double likvideBeholdninger;
        private double aktiekapital;
        private double overførteOverskud;
        private double forslagTilUdbytte;
        private double hensatteForpligtelser;
        private double langfristetGæld;
        private double kortfristetGæld;

        private List<Postering> minePosteringer;

        // konstruktør
        public Årsregnskab(int årstal)
        {
            this.årstal = årstal;
            immaterielle = 0;
            materielle = 0;
            finansielle = 0;
            varebeholdninger = 0;
            tilgodehavender = 0;
            værdipapirer = 0;
            likvideBeholdninger = 0;
            aktiekapital = 0;
            overførteOverskud = 0;
            forslagTilUdbytte = 0;
            hensatteForpligtelser = 0;
            langfristetGæld = 0;
            kortfristetGæld = 0;

            minePosteringer = new List<Postering>();
        }

        #region Associerings metoder

        // metode til at skabe associeringen mellem et årsregnskabs-objekt og et posterings-objekt
        public void TilknytPostering(Postering enPostering)
        {
            minePosteringer.Add(enPostering);
        }

        // metode til at fjerne associeringen mellem et årsregnskabs-objekt og et posterings-objekt
        public void FjernPosteringsTilknytning(Postering enPostering)
        {
            minePosteringer.Remove(enPostering);
        }

        // metode til at hente listen med associerede posterings-objekter
        public IEnumerator GetMinePosteringer()
        {
            return minePosteringer.GetEnumerator();
        }

        #endregion

        #region Metoder til at udregne og returnere de forskellige værdier i resultatopgørelsen

        // metode til at returnere nettoomsætningen
        public double GetNettoomsætning()
        {
            double nettoomsætning = 0;

            foreach (Postering post in minePosteringer)
            {
                if (post.PosteringsType == "Nettoomsætning" && post.Aktiv == true)
                {
                    nettoomsætning += post.Beløb;
                }
            }
            return nettoomsætning;
        }

        // metode til at returnere produktionsomkostninger
        public double GetProduktionsomkostninger()
        {
            double produktionsomkostning = 0;

            foreach (Postering post in minePosteringer)
            {
                if (post.PosteringsType == "Produktionsomkostning" && post.Aktiv == true)
                {
                    produktionsomkostning += post.Beløb;
                }
            }
            return produktionsomkostning;
        }

        // metode til at returnere bruttoresultatet
        public double GetBruttoresultat()
        {
            double nettoomsætning = GetNettoomsætning();
            double produktionsomkostninger = GetProduktionsomkostninger();
            
            double bruttoresultat = nettoomsætning - produktionsomkostninger;
            return bruttoresultat;
        }

        // metode til at returnere distributionsomkostning
        public double GetDistributionsomkostning()
        {
            double distributionsomkostning = 0;

            foreach (Postering post in minePosteringer)
            {
                if (post.PosteringsType == "Distributionsomkostning" && post.Aktiv == true)
                {
                    distributionsomkostning += post.Beløb;
                }
            }
            return distributionsomkostning;
        }

        // metode til at returnere administrationsomkostning
        public double GetAdministrationsomkostning()
        {
            double administrationsomkostning = 0;

            foreach (Postering post in minePosteringer)
            {
                if (post.PosteringsType == "Administrationsomkostning" && post.Aktiv == true)
                {
                    administrationsomkostning += post.Beløb;
                }
            }
            return administrationsomkostning;
        }

        // metode til at returnere resultatet af primær drift
        public double GetResultatPrimærDrift()
        {
            double bruttoresultat = GetBruttoresultat();
            double distributionsomkostning = GetDistributionsomkostning();
            double administrationsomkostning = GetAdministrationsomkostning();
            
            double resultatPrimærDrift = bruttoresultat - distributionsomkostning - administrationsomkostning;
            return resultatPrimærDrift;
        }

        // metode til at returnere den finansielle omkostning netto
        public double GetFinansielOmkostningNetto()
        {
            double finansielOmkostning = 0;

            foreach (Postering post in minePosteringer)
            {
                if (post.PosteringsType == "Finansiel omkostning netto")
                {
                    finansielOmkostning += post.Beløb;
                }
            }
            return finansielOmkostning;
        }

        // metode til at returnere årets resultat
        public double GetÅretsResultat()
        {
            double resultatPrimærDrift = GetResultatPrimærDrift();
            double finansielOmkostning = GetFinansielOmkostningNetto();
            
            double åretsResultat = resultatPrimærDrift - finansielOmkostning;
            return åretsResultat;
        }

        #endregion

        #region Metoder til at udregne og returnere de resterende værdier i balancen

        // metode til at returnere beløbet for de samlede anlægsaktiver
        public double GetAnlægsaktiver()
        {
            double anlægsaktiver = immaterielle + materielle + finansielle;
            return anlægsaktiver;
        }

        // metode til at returnere beløbet for de samlede omsætningsaktiver
        public double GetOmsætningsaktiver()
        {
            double omsætningsaktiver = varebeholdninger + tilgodehavender + værdipapirer + likvideBeholdninger;
            return omsætningsaktiver;
        }

        // metode til at returnere beløbet for de samlede aktiver
        public double GetAktiverIAlt()
        {
            double anlægsaktiver = GetAnlægsaktiver();
            double omsætningsaktiver = GetOmsætningsaktiver();
            
            double aktiverIAlt = anlægsaktiver + omsætningsaktiver;
            return aktiverIAlt;
        }

        // metode til at returnere beløbet for den samlede egenkapital
        public double GetEgenkapital()
        {
            double egenkapital = aktiekapital + overførteOverskud + forslagTilUdbytte;
            return egenkapital;
        }

        // metode til at returnere beløbet for de samlede gældsforpligtelser
        public double GetGældsforpligtelser()
        {
            double gældsforpligtelser = kortfristetGæld + langfristetGæld;
            return gældsforpligtelser;
        }

        // metode til at returnere beløbet for de samlede passiver
        public double GetPassiverIAlt()
        {
            double egenkapital = GetEgenkapital();
            double gældsforpligtelser = GetGældsforpligtelser();
            
            double passiverIAlt = egenkapital + hensatteForpligtelser + gældsforpligtelser;
            return passiverIAlt;
        }

        #endregion

        #region Metoder til at udregne og returnere nøgletallene til rentabilitetsanalysen

        // metode til at returnere afkastningsgraden
        public double GetAfkastningsgrad()
        {
            double resultatPrimærDrift = GetResultatPrimærDrift();
            double aktiverIAlt = GetAktiverIAlt();
            double afkastningsgrad = (resultatPrimærDrift * 100) / aktiverIAlt;

            return afkastningsgrad;
        }

        // metode til at returnere overskudsgraden
        public double GetOverskudsgrad()
        {
            double resultatPrimærDrift = GetResultatPrimærDrift();
            double omsætning = GetNettoomsætning();
            double overskudsgrad = (resultatPrimærDrift * 100) / omsætning;

            return overskudsgrad;
        }

        // metode til at returnere aktivernes omsætningshastighed
        public double GetAktivernesOmsætningshastighed()
        {
            double omsætning = GetNettoomsætning();
            double aktiverIAlt = GetAktiverIAlt();

            double omsætningshastighed = omsætning / aktiverIAlt;
            return omsætningshastighed;
        }

        // metode til at returnere egenkapitalens forretning
        public double GetEgenkapitalensForretning()
        {
            double åretsResultat = GetÅretsResultat();
            double egenkapital = GetEgenkapital();
            double forretning = (åretsResultat * 100) / egenkapital;

            return forretning;
        }

        // metode til at returnere fremmedkapitalens forretning
        public double GetFremmedkapitalensForretning()
        {
            double finasielOmkostning = GetFinansielOmkostningNetto();
            double gældsforpligtelser = GetGældsforpligtelser();
            double forretning = (finasielOmkostning * 100) / gældsforpligtelser;

            return forretning;
        }

        #endregion

        #region Metoder til at udregne og returnere nøgletallene til analysen af indtjeningsevnen

        // metode til at returnere dækningsgraden
        public double GetDækningsgrad()
        {
            double dækningsbidrag = GetBruttoresultat();
            double omsætning = GetNettoomsætning();
            
            double dækningsgrad = (dækningsbidrag * 100) / omsætning;
            return dækningsgrad;
        }

        // metode til at returnere nulpunktsomsætningen
        public double GetNulpunktsomsætning()
        {
            double distribustionsomkostning = GetDistributionsomkostning();
            double administrationsomkostning = GetAdministrationsomkostning();
            double dækningsgrad = GetDækningsgrad();

            double nulpunktsomsætning = ((distribustionsomkostning + administrationsomkostning) * 100) / dækningsgrad;
            return nulpunktsomsætning;
        }

        // metode til at returnere sikkerhedsmarginen
        public double GetSikkerhedsMargin()
        {
            double faktiskOmsætning = GetNettoomsætning();
            double nulpunktsomsætning = GetNulpunktsomsætning();

            double sikkerhedsmargin = (faktiskOmsætning - nulpunktsomsætning) / faktiskOmsætning;
            return sikkerhedsmargin;
        }

        // metode til at returnere kapacitetsgraden
        public double GetKapacitetsgrad()
        {
            double distribustionsomkostning = GetDistributionsomkostning();
            double administrationsomkostning = GetAdministrationsomkostning();
            double bruttoresultat = GetBruttoresultat();

            double kapacitetsgrad = bruttoresultat / (distribustionsomkostning + administrationsomkostning);
            return kapacitetsgrad;
        }

        #endregion

        #region Metoder til at udregne og returnere nøgletallene til analysen af kapitaltilpasningen

        // metode til at returnere anlægsaktivernes omsætningshastighed
        public double GetAnlægsaktivernesOmsætningshastighed()
        {
            double omsætning = GetNettoomsætning();
            double anlægsaktiver = GetAnlægsaktiver();

            double omsætningshastighed = omsætning / anlægsaktiver;
            return omsætningshastighed;
        }

        // metode til at returnere den materielle omsætningshastighed
        public double GetMaterielleOmsætningshastighed()
        {
            double omsætning = GetNettoomsætning();

            double omsætningshastighed = omsætning / materielle;
            return omsætningshastighed;
        }

        // metode til at returnere varelagerets omsætningshastighed
        public double GetVarelagrenesOmsætningshastighed()
        {
            double produktionsomkostninger = GetProduktionsomkostninger();

            double omsætningshastighed = produktionsomkostninger / varebeholdninger;
            return omsætningshastighed;
        }

        // metode til at returnere lagerdage
        public double GetLagerdage()
        {
            double omsætningshastighed = GetVarelagrenesOmsætningshastighed();

            double lagerdage = 365 / omsætningshastighed;
            return lagerdage;
        }

        // metode til at returnere varedebitorernes omsætningshastighed
        public double GetVaredebitorernesOmsætningshastighed()
        {
            double omsætning = GetNettoomsætning();

            double omsætningshastighed = omsætning / tilgodehavender;
            return omsætningshastighed;
        }

        // metode til at returnere kreditdage
        public double GetKreditdage()
        {
            double omsætningshastighed = GetVaredebitorernesOmsætningshastighed();

            double kreditdage = 365 / omsætningshastighed;
            return kreditdage;
        }

        #endregion

        #region Metoder til at udregne og returnere nøgletallene til analysen af soliditet og likviditet

        // metode til at returnere soliditetsgraden
        public double GetSoliditetsgrad()
        {
            double egenkapital = GetEgenkapital();
            double aktiver = GetAktiverIAlt();

            double soliditetsgrad = (egenkapital * 100) / aktiver;
            return soliditetsgrad;
        }

        // metode til at returnere likviditetsgrad 1
        public double GetLikviditetsgrad1()
        {
            double omsætningsaktiver = GetOmsætningsaktiver();

            double likviditetsgrad1 = ((omsætningsaktiver - varebeholdninger) * 100) / kortfristetGæld;
            return likviditetsgrad1;
        }

        // metode til at returnere likviditetsgrad 2
        public double GetLikviditetsgrad2()
        {
            double omsætningsaktiver = GetOmsætningsaktiver();

            double likviditetsgrad1 = (omsætningsaktiver * 100) / kortfristetGæld;
            return likviditetsgrad1;
        }

        #endregion

        #region Properties

        public int Årstal
        {
            get { return årstal; }
        }

        public double Immaterielle
        {
            get { return immaterielle; }
            set { immaterielle = value; }
        }

        public double Materielle
        {
            get { return materielle; }
            set { materielle = value; }
        }

        public double Finansielle
        {
            get { return finansielle; }
            set { finansielle = value; }
        }

        public double Varebeholdninger
        {
            get { return varebeholdninger; }
            set { varebeholdninger = value; }
        }

        public double Tilgodehavender
        {
            get { return tilgodehavender; }
            set { tilgodehavender = value; }
        }

        public double Værdipapirer
        {
            get { return værdipapirer; }
            set { værdipapirer = value; }
        }

        public double LikvideBeholdninger
        {
            get { return likvideBeholdninger; }
            set { likvideBeholdninger = value; }
        }

        public double Aktiekapital
        {
            get { return aktiekapital; }
            set { aktiekapital = value; }
        }

        public double OverførteOverskud
        {
            get { return overførteOverskud; }
            set { overførteOverskud = value; }
        }

        public double ForslagTilUdbytte
        {
            get { return forslagTilUdbytte; }
            set { forslagTilUdbytte = value; }
        }

        public double HensatteForpligtelser
        {
            get { return hensatteForpligtelser; }
            set { hensatteForpligtelser = value; }
        }

        public double LangfristetGæld
        {
            get { return langfristetGæld; }
            set { langfristetGæld = value; }
        }

        public double KortfristetGæld
        {
            get { return kortfristetGæld; }
            set { kortfristetGæld = value; }
        }

        # endregion
    }
}
